package com.hmall.search.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.hmall.common.domain.CustomPageDTO;
import com.hmall.common.domain.PageDTO;
import com.hmall.search.domain.dto.ItemDTO;
import com.hmall.search.domain.es.ItemEs;
import com.hmall.search.domain.query.ItemPageQuery;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortMode;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.AggregationsContainer;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {

    private final ElasticsearchRestTemplate elasticsearchRestTemplate;


//    @ApiOperation("搜索商品")
//    @GetMapping("/list")
//    public PageDTO<ItemDTO> search(ItemPageQuery query) {
//        // 分页查询
//        Page<Item> result = searchService.lambdaQuery()
//                .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
//                .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
//                .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
//                .eq(Item::getStatus, 1)
//                .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
//                .page(query.toMpPage("update_time", false));
//        // 封装并返回
//        return PageDTO.of(result, ItemDTO.class);
//    }

    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO<ItemDTO> search(ItemPageQuery query) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        // 构建 Bool 查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        if (StrUtil.isNotBlank(query.getKey())) {
            boolQuery.must(QueryBuilders.matchQuery("name", query.getKey()));
        }

        if (StrUtil.isNotBlank(query.getBrand())) {
            boolQuery.filter(QueryBuilders.termQuery("brand", query.getBrand()));
        }

        if (StrUtil.isNotBlank(query.getCategory())) {
            boolQuery.filter(QueryBuilders.termQuery("category", query.getCategory()));
        }

        if (query.getMinPrice() != null && query.getMaxPrice() != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price")
                    .gte(query.getMinPrice()).lte(query.getMaxPrice()));
        }

        // Function Score：广告商品加权，让 isAD=true 的商品排前面
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                boolQuery,
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                QueryBuilders.termQuery("isAD", true),
                                ScoreFunctionBuilders.weightFactorFunction(10)
                        ),
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                ScoreFunctionBuilders.weightFactorFunction(1)
                        )
                }
        ).scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);

        builder.withQuery(functionScoreQuery);

        // 排序：前端传了 sortBy 就用它，否则默认 updateTime 降序
        String sortField = query.getSortBy();
        if (StrUtil.isNotBlank(sortField)) {
            builder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.DESC));
        }

        // 分页
        PageRequest pageRequest = PageRequest.of(query.getPageNo() - 1, query.getPageSize());
        builder.withPageable(pageRequest);

        // 执行查询
        SearchHits<ItemEs> hits = elasticsearchRestTemplate.search(builder.build(), ItemEs.class);

        // 封装结果
        List<ItemDTO> dtoList = hits.getSearchHits().stream()
                .map(hit -> BeanUtil.copyProperties(hit.getContent(), ItemDTO.class))
                .collect(Collectors.toList());

        long total = hits.getTotalHits();
        int size = query.getPageSize();
        long pages = (total + size - 1) / size;
        return new PageDTO<>(total, pages, dtoList);
    }

    @ApiOperation("过滤条件")
    @PostMapping("/filters")
    public Map<String, List<String>> filters(@RequestBody ItemPageQuery query) {
        // 1. 构建查询条件
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        // 1.1 搜索关键字（根据 name 字段）
        if (StrUtil.isNotBlank(query.getKey())) {
            builder.withQuery(QueryBuilders.matchQuery("name", query.getKey()));
        }

        // 1.2 固定筛选条件：仅展示状态为上架的商品
        builder.withFilter(QueryBuilders.termQuery("status", 1));

        // 2. 添加聚合条件（分类 + 品牌）
        builder.addAggregation(AggregationBuilders.terms("categoryAgg").field("category").size(100));
        builder.addAggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));

        // 3. 不返回商品数据，仅聚合信息
        builder.withPageable(PageRequest.of(0, 1));

        // 4. 执行查询
        SearchHits<ItemEs> searchHits = elasticsearchRestTemplate.search(builder.build(), ItemEs.class);

        // 5. 获取并解析聚合结果
        AggregationsContainer<?> aggregationsContainer = searchHits.getAggregations();
        Terms categoryTerms = null;
        Terms brandTerms = null;
        if (aggregationsContainer != null) {
            Aggregations aggregations = (Aggregations) aggregationsContainer.aggregations();
            categoryTerms = aggregations.get("categoryAgg");
            brandTerms = aggregations.get("brandAgg");

        }
        List<String> categories = Optional.ofNullable(categoryTerms)
                .map(t -> t.getBuckets().stream()
                        .map(Terms.Bucket::getKeyAsString)
                        .collect(Collectors.toList()))
                .orElse(Collections.emptyList());

        List<String> brands = Optional.ofNullable(brandTerms)
                .map(t -> t.getBuckets().stream()
                        .map(Terms.Bucket::getKeyAsString)
                        .collect(Collectors.toList()))
                .orElse(Collections.emptyList());

        Map<String, List<String>> result = new HashMap<>();
        result.put("category", categories);
        result.put("brand", brands);
        return result;
    }
}
